package org.hoyi.servmotions;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.HiddenFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.hoyi.DB.ctrl.Console;
import org.hoyi.ctrls.sys.sh.ShellCtrls;
import org.hoyi.microservice.HoyiCloudApplication;
import org.hoyi.servmotions.motionFileListener;
import org.hoyi.util.DateTimeUtil;

public class hoyi_motionrunner {

	public static Thread loaderThread;
	/**
	 * 开始监听项目是否更新.
	 * @param args
	 */
	public static void Begin_Motion(String _cmd, String[] _paths) {
		motion_cmd = _cmd;
		motion_paths = _paths;
		
		Console.Info("hoyi motion, hoyi-web 服务监听启动！将会监听您的工作目录修改，自动重启您的hoyi-web服务.～");
		Run();
		loaderThread = AsynLoadMain();
	}
	/**
	 * 【必传】
	 * 有更新后，用于启动的项目的方法，
	 * 获取方法：
	 * 找到 Run Configurations,
	 * 找到要启动的项目，点击：Show Command Line,这个就是要传入的cmd,
	 * 
	 * PS: 要注意启动的类不是监听的类，如果填成监听的类，会造成死循环.
	 */
	public static String motion_cmd = "";
	/**
	 * 【必传】
	 * 监听的路径，监听传入的路径+"/target";
	 * 当前项目请用".",多项目工程请用硬盘目录，逗号分割.
	 * 		例如：
	 * 		motion_paths = {
			".","/Users/sae/Documents/workspace_show/show-shop"
			};
	 */
	public static String[] motion_paths = {};
	

	public static void Run() {
		Thread _thread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				ShellCtrls _shell = new ShellCtrls();
				String osname = _shell.GetOsName();
				if (osname.toLowerCase().contains("windows")) {
					Console.Info("windows 未测试");
					String run_cmd =  motion_cmd ;
					String result =  _shell.execCmd(run_cmd, null);
					Console.Info(run_cmd + "\n" + result);
				}else {
					String run_cmd = "nohup " + motion_cmd + " &";
					String result =  _shell.execCmd(run_cmd, null);
					Console.Info(run_cmd + "\n" + result);
				}
			}
		});
		_thread.start();
	}
	
	public static long start_runtime = -1;
	public static long end_runtime = -1;
	
	public static void Restart() {
		boolean canrestart = false;
		if(start_runtime == -1) {
			canrestart = true;
		}else {
			if(System.currentTimeMillis() - end_runtime > HoyiCloudApplication.Motion_Page_Newest_millons) {
				canrestart = true;
			}
		}
		if(canrestart) {
			Console.Info("Restart.time: " + DateTimeUtil.getCurrentDateTime());
			start_runtime = System.currentTimeMillis();
			hoyi_motionrunner.Run();
			end_runtime = System.currentTimeMillis();
		}else {
			Console.Info("Restart:小于" + HoyiCloudApplication.Motion_Page_Newest_millons + "ms，稍后重启");
			try {
				Thread.sleep(HoyiCloudApplication.Motion_Page_Newest_millons);

				Console.Info("Restart.time: " + DateTimeUtil.getCurrentDateTime());
				start_runtime = System.currentTimeMillis();
				hoyi_motionrunner.Run();
				end_runtime = System.currentTimeMillis();
			} catch (InterruptedException e) {
				Console.Info(e.getMessage());
			}
		}
	}
	/**
	 * 监控这些目录，如果有文件修改，则重新加载.
	 * 
	 * @param motionpath
	 */
	public static void BeginMotionModule(String[] motionpath) {
		// 轮询间隔 5 秒
		long interval = TimeUnit.SECONDS.toMillis(1);
		// 创建过滤器
		IOFileFilter directories = FileFilterUtils.and(FileFilterUtils.directoryFileFilter(),
				HiddenFileFilter.VISIBLE);
		IOFileFilter files = FileFilterUtils.or(FileFilterUtils.fileFileFilter(),
				FileFilterUtils.suffixFileFilter(".jar"));
		IOFileFilter filter = FileFilterUtils.or(directories, files);

		List<FileAlterationObserver> observers = new ArrayList<FileAlterationObserver>();
		Runnable restart_runnable = new Runnable() {
			
			@Override
			public void run() {
				hoyi_motionrunner.Restart();
			}
		};
		for (String sin_path : motionpath) {
			File cur = new File(sin_path);
			File _truepath = new File(cur.getAbsolutePath() + "/target");
			// 使用过滤器
			FileAlterationObserver observer = new FileAlterationObserver(_truepath, filter);
			observer.addListener(new motionFileListener(restart_runnable));
			observers.add(observer);

//			File _truepath1 = new File(cur.getAbsolutePath() + "/src");
//			// 使用过滤器
//			FileAlterationObserver observer1 = new FileAlterationObserver(_truepath1, filter);
//			observer1.addListener(new motionFileListener(restart_runnable));
//			observers.add(observer1);
		}
		// 创建文件变化监听器
		FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
        if (observers != null) {
            for (FileAlterationObserver observer : observers) {
            	monitor.addObserver(observer);
            }
        }
		// 开始监控
		try {
			monitor.start();
		} catch (Exception e) {
			Console.Info(e.getMessage());
		}
	}

	/**
	 * 开线程调用Load.
	 * 
	 * @param modules_path
	 * @param loaderclass
	 */
	public static Thread AsynLoadMain() {
		Thread loaderThread = new Thread(new Runnable() {
			@Override
			public void run() {
				BeginMotionModule(motion_paths);
			}
		});
		loaderThread.start();
		return loaderThread;
	}
}
